<?php

/**
 * Created by PhpStorm.
 * User: wz_zh
 * Date: 2017/11/9
 * Time: 15:30
 */

namespace PKFrame\Extend;
defined('PATH_PK') or die();


class Fsocketopen
{

    private static $_params = [];

    /**
     * 获取 HTTP 源代码
     * @param string $url
     * @return bool|string
     */
    public static function GetHttpCode($url = '')
    {
        list($host, $port, $path, $query) = self::_params($url);
        $fp = self::_fsocketopen($host, $port, $errno, $errstr, LONG_RANGE_TIMEOUT);
        if (empty($fp)) {
            return false;
        }
        $result = '';
        $out = "GET /" . $path . '?' . $query . " HTTP/1.0\r\n";
        $out .= "Host: $host\r\n";
        $out .= "Connection: Close\r\n\r\n";
        @fwrite($fp, $out);
        $http_200 = preg_match('/200/', @fgets($fp, 1024));
        if (!$http_200) {
            return false;
        }
        $first_header = fgets($fp, 1024);
        if (trim($first_header) == "") {
            return false;
        }
        while (!@feof($fp)) {
            if (isset($get_info) && $get_info) {
                $result .= @fread($fp, 1024);
            } else {
                if (@fgets($fp, 1024) == "\r\n") {
                    $get_info = true;
                }
            }
        }
        @fclose($fp);
        return $result;
    }

    /**
     * fsock 方法获取远程文件的大小
     * @param string $url 远程文件的路径
     * @return int|string
     */
    public static function GetHttpSize($url = '')
    {
        list($host, $port, $path) = self::_params($url);
        $fp = self::_fsocketopen($host, $port, $errno, $errstr, LONG_RANGE_TIMEOUT);
        if (empty($fp)) {
            return false;
        }
        $out = "HEAD " . $path . " HTTP/1.1\r\n";
        $out .= "Host: " . $host . "\r\n";
        $out .= "Connection: Close\r\n\r\n";
        fwrite($fp, $out);
        $http_200 = preg_match('/HTTP.*200/', @fgets($fp, 1024));
        if (!$http_200) {
            return false;
        }
        $size = 0;
        while (!feof($fp)) {
            $header = fgets($fp);
            if (stripos($header, 'Content-Length') !== false) {
                $size = trim(substr($header, strpos($header, ':') + 1));
            }
        }
        fclose($fp);
        return $size;
    }

    private static function _params($url = ''): array
    {
        self::$_params = parse_url($url);
        $host = self::$_params['host'];
        $port = isset(self::$_params['port']) ? self::$_params['port'] : "80";
        self::$_params['scheme'] != 'https' ?: $port = '443';
        $path = self::$_params['path'];
        $query = self::$_params['query'];
        return array($host, $port, $path, $query);
    }

    /**
     * fsocketopen 形式通信
     * @param string $hostname 主机名
     * @param int $port 主机的端口号
     * @param int $errno 错误编号
     * @param string $errStr 错误信息
     * @param int $timeout 超时时间
     * @return false|resource|string
     */
    private static function _fsocketopen(string $hostname, int $port, &$errno, &$errStr, $timeout = 15)
    {
        $fp = '';
        self::$_params['scheme'] != 'https' ?: $hostname = 'ssl://' . $hostname;
        try {
            if (function_exists('fsockopen')) {
                $fp = @fsockopen($hostname, $port, $errno, $errStr, $timeout);
            } elseif (function_exists('pfsockopen')) {
                $fp = @pfsockopen($hostname, $port, $errno, $errStr, $timeout);
            } elseif (function_exists('stream_socket_client')) {
                $fp = @stream_socket_client($hostname . ':' . $port, $errno, $errStr, $timeout);
            } else {
                throw new \Exception('php extend fsockopen no exists');
            }
        } catch (\Exception $exception) {
            handlerException($exception);
        }
        return $fp;
    }
}
